@file:Suppress("DEPRECATION")

package com.jerry.usbserial.fragment.usb

import android.Manifest
import android.app.ProgressDialog
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.location.LocationManager
import android.net.wifi.WifiManager
import android.os.Build
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AlertDialog
import androidx.core.location.LocationManagerCompat
import com.jerry.usbserial.R
import com.jerry.usbserial.adapter.ConsoleAdapter
import com.jerry.usbserial.util.*
import com.jerry.usbserial.util.download.DownloadManager
import com.jerry.usbserial.util.download.OnDownloadListener
import com.jerry.usbserial.util.task.udp.UDPMiddleTask
import com.jerry.usbserial.util.task.usb.UsbFirmwareTask
import kotlinx.android.synthetic.main.bar_common.*
import kotlinx.android.synthetic.main.frg_firmware_update.*
import kotlinx.android.synthetic.main.part_frg_firmware_update.*
import permissions.dispatcher.NeedsPermission
import permissions.dispatcher.OnPermissionDenied
import permissions.dispatcher.RuntimePermissions
import java.io.File
import java.text.SimpleDateFormat
import java.util.*

/**
 * Created by dugang on 2020/6/6.
 */
@RuntimePermissions
class UsbFirmwareFragment : UsbFragment() {
    private val downloadManager: DownloadManager by lazy { DownloadManager(mContext.downloadPath()) }
    private val mConsoleAdapter: ConsoleAdapter by lazy { ConsoleAdapter(mContext) }

    override val layoutId: Int = R.layout.frg_firmware_update

    private var countNumber = 0

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // toolbar
        toolbar_title.text = "系统固件升级模式"
        toolbar_title.setOnClickListener {
            if (countNumber == 10) {
                mContext.showToast("中固件升级已开启,请谨慎使用!")
                toolbar.menu.getItem(0).isVisible = true
                mCanRegister = true
                registerReceiver()
                requestPermissionWithPermissionCheck()
            }
            countNumber++
        }
        toolbar.inflateMenu(R.menu.firmware_update)
        toolbar.setOnMenuItemClickListener {
            if (it.itemId == R.id.middleUpdate) {
                if (mIPAddress.isNullOrEmpty()) {
                    mContext.showToast("无法获取手机 IP 地址,请打开 GPS 并连接 WIFI")
                } else {
                    AlertDialog.Builder(mContext)
                        .setTitle("提示")
                        .setMessage("确认手机和设备已连接同一 WiFi!")
                        .setCancelable(false)
                        .setPositiveButton("开始升级") { _, _ -> commitCheck(middleCommit = true) }
                        .setNegativeButton(android.R.string.cancel, null)
                        .show()
                }
                return@setOnMenuItemClickListener true
            }
            return@setOnMenuItemClickListener false
        }
        // 日志
        consoleList.adapter = mConsoleAdapter

        // 数据提交
        bt_commit.setOnClickListener { commitCheck() }

        // 初始化数据
        et_sn.setText(mContext.getSp().getString("sn", ""))
        et_storeid.setText(mContext.getSp().getString("storeid", ""))
        et_user.setText(mContext.getSp().getString("user", ""))
        et_storename.setText(mContext.getSp().getString("storename", ""))
        et_tel.setText(mContext.getSp().getString("tel", ""))
        et_address.setText(mContext.getSp().getString("address", ""))


        if (!mContext.getSp().getString("ver", "").isNullOrEmpty()) bt_commit.performClick()
    }

    private fun commitCheck(middleCommit: Boolean = false) {
        // 隐藏掉键盘
        hideSoftInput()

        val sn = et_sn.text.toString()
        val storeId = et_storeid.text.toString()
        val user = et_user.text.toString()
        val storeName = et_storename.text.toString()
        val tel = et_tel.text.toString()
        val address = et_address.text.toString()

        var hasErr = true
        when {
            sn.length != 12 || !sn.startsWith("70890188") -> {
                mContext.showToast("设备序列号无效!")
            }
            storeId.isEmpty() -> {
                mContext.showToast("国际餐厅编码不能为空!")
            }
            user.isEmpty() -> {
                mContext.showToast("负责人不能为空!")
            }
            storeName.isEmpty() -> {
                mContext.showToast("门店名称不能为空!")
            }
            tel.isEmpty() || tel.length != 11 -> {
                mContext.showToast("联系电话无效!")
            }
            address.isEmpty() -> {
                mContext.showToast("门店地址不能为空!")
            }
            else -> {
                hasErr = false
            }
        }
        if (!hasErr && !downloadManager.hasTask()) {
            bt_commit.isEnabled = false
            commitInfo(sn, storeId, storeName, user, tel, address, middleCommit = middleCommit)
        }
    }

    private fun commitInfo(
        sn: String,
        storeId: String,
        storeName: String,
        user: String,
        tel: String,
        address: String,
        func: String = "1",
        middleCommit: Boolean = false
    ) {
        RemoteRepo.getApi().commit(sn, storeId, storeName, user, tel, address, func = func)
            .applySchedulers(this)
            .subscribe(object : ResultObserver<CommitResult>() {
                override fun handlerSuccess(data: CommitResult) {
                    bt_commit.isEnabled = true
                    if (func == "1") {
                        if (data.code == "1") {
                            mContext.setSp("sn", sn)
                            mContext.setSp("storeid", storeId)
                            mContext.setSp("storename", storeName)
                            mContext.setSp("user", user)
                            mContext.setSp("tel", tel)
                            mContext.setSp("address", address)

                            if (middleCommit) startMiddleTask(data) else startUpdateTask(data)
                        } else {
                            mContext.showToast("网络超时")
                        }
                    }
                }

                override fun handlerError(code: Int, msg: String) {
                    mContext.showToast("网络超时")
                    bt_commit.isEnabled = true
                }
            })
    }

    private fun sendLog() {
        val sn = mContext.getSp().getString("sn", "") ?: ""
        val storeId = mContext.getSp().getString("storeid", "") ?: ""
        val user = mContext.getSp().getString("user", "") ?: ""
        val storeName = mContext.getSp().getString("storename", "") ?: ""
        val tel = mContext.getSp().getString("tel", "") ?: ""
        val address = mContext.getSp().getString("address", "") ?: ""
        val date = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(Date())
        val log = mConsoleAdapter.getList().toJson()

        RemoteRepo.getApi().commit(sn, storeId, storeName, user, tel, address, date = date, log = log, func = "3")
            .applySchedulers(this)
            .subscribe(object : ResultObserver<CommitResult>() {
                override fun handlerSuccess(data: CommitResult) {
                }

                override fun handlerError(code: Int, msg: String) {
                }
            })
    }

    private fun startUpdateTask(result: CommitResult) {
        val firmwareUrl = result.add1 ?: ""
        val firmwareCrc = result.add1_crc ?: ""
        val imageUrl = result.add2 ?: ""
        val imageCrc = result.add2_crc ?: ""

        val firmwareFile = File(mContext.downloadPath(), firmwareUrl.getFileName())
        val imageFile = File(mContext.downloadPath(), imageUrl.getFileName())

        val usbService = getUsbService()

        when {
            // 判断是否可以升级
            result.ver == "0" -> {
                AlertDialog.Builder(mContext).apply {
                    setTitle("提示")
                    setMessage("固件升级已关闭,请选择菜单升级!")
                    setCancelable(false)
                    setPositiveButton("确定") { _, _ ->
                        startActivity(mContext.packageManager.getLaunchIntentForPackage(mContext.packageName)?.apply {
                            addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
                        })
                    }
                }.show()
            }
            // 版本低于服务器端版本,下载新固件
            result.ver != mContext.getSp().getString("ver", "") -> {
                mContext.setSp("ver", result.ver)

                firmwareFile.delete()
                downloadFirmware(firmwareUrl, result)

                imageFile.delete()
                downloadImage(imageUrl, result)

            }
            // 判断固件是否有缺失
            !firmwareFile.exists() -> downloadFirmware(firmwareUrl, result)
            !imageFile.exists() -> downloadImage(imageUrl, result)
            // 判断是否有下载任务
            downloadManager.hasTask() -> mConsoleAdapter.add("文件下载中")
            // 文件 crc 校验
            !firmwareFile.matchCrc(firmwareCrc) -> {
                mConsoleAdapter.add("小固件校验失败,文件重新下载中")
                firmwareFile.delete()
                downloadFirmware(firmwareUrl, result)
            }
            !imageFile.matchCrc(imageCrc) -> {
                mConsoleAdapter.add("镜像文件校验失败,文件重新下载中")
                imageFile.delete()
                downloadImage(imageUrl, result)
            }
            // 判断升级是否未完成
            hasTask() -> mConsoleAdapter.add("有未完成的升级任务")
            // 判断设备是否连接
            !isDeviceConnected() -> mConsoleAdapter.add("请连接设备!")
            // 判断 Usb 服务是否可用
            usbService == null -> mConsoleAdapter.add("Usb服务不可用")

            // 开始升级
            else -> {
                mConsoleAdapter.clear()
                mConsoleAdapter.add("升级检查完成,开始升级...")
                bt_commit.isEnabled = false
                startTask(UsbFirmwareTask(mContext, usbService, firmwareFile, imageFile))
            }
        }
    }


    override fun onMessageEvent(event: MsgEvent) {
        super.onMessageEvent(event)
        when (event.code) {
            MsgEventCode.STATE -> {
                // 连接设备, 没有升级任务时检测下载并自动开始升级
//                mConsoleAdapter.add((event.msg == "设备已连接").toString())
//                mConsoleAdapter.add((!hasTask()).toString())
//                mConsoleAdapter.add((!downloadManager.hasTask()).toString())

                if (event.msg == "设备已连接" && !hasTask() && !downloadManager.hasTask()) {
                    commitCheck()
                }
                mConsoleAdapter.add(event.msg ?: "")
            }
            MsgEventCode.MESSAGE -> {
                mConsoleAdapter.add(event.msg ?: "")
            }
            MsgEventCode.PROCESS -> {
                progressBar.visibility = if (event.process == 100) View.INVISIBLE else View.VISIBLE
                progressBar.setProgress(event.process)
            }
            MsgEventCode.ERROR -> {
                closeTask()
                progressBar.visibility = View.INVISIBLE
                bt_commit.isEnabled = true
                sendLog()

                AlertDialog.Builder(mContext).apply {
                    setTitle("提示")
                    setMessage(event.msg)
                    setCancelable(false)
                    setPositiveButton("确定") { _, _ -> }
                }.show()
            }
            MsgEventCode.COMPLETED -> {
                mConsoleAdapter.add(event.msg ?: "")
                closeTask()
                bt_commit.isEnabled = true
                progressBar.visibility = View.INVISIBLE
                // 升级完成提交数据
                val sn = mContext.getSp().getString("sn", "") ?: ""
                val storeId = mContext.getSp().getString("storeid", "") ?: ""
                val user = mContext.getSp().getString("user", "") ?: ""
                val storeName = mContext.getSp().getString("storename", "") ?: ""
                val tel = mContext.getSp().getString("tel", "") ?: ""
                val address = mContext.getSp().getString("address", "") ?: ""
                commitInfo(sn, storeId, storeName, user, tel, address, "2")
            }
        }
    }


    private fun downloadImage(fileUrl: String, result: CommitResult) {
        val taskId = downloadManager.addTask(fileUrl)
        downloadManager.registerListener(taskId, object : OnDownloadListener {
            override fun onPending() {
                mConsoleAdapter.add("镜像文件下载中...")
                progressBar.visibility = View.VISIBLE
            }

            override fun onProgress(progress: Long, total: Long) {
                progressBar.setProgress((progress * 100 / total).toInt())
            }

            override fun onCompleted(file: File) {
                progressBar.visibility = View.INVISIBLE
                mConsoleAdapter.add("镜像下载完成")
                startUpdateTask(result)
            }

            override fun onPaused() {
            }

            override fun onCanceled() {
            }

            override fun onFailed() {
            }
        })
        downloadManager.start(taskId)
    }

    private fun downloadFirmware(fileUrl: String, result: CommitResult) {
        val taskId = downloadManager.addTask(fileUrl)
        downloadManager.registerListener(taskId, object : OnDownloadListener {
            override fun onPending() {
                mConsoleAdapter.add("固件文件下载中...")
            }

            override fun onProgress(progress: Long, total: Long) {

            }

            override fun onCompleted(file: File) {
                mConsoleAdapter.add("固件下载完成")
                startUpdateTask(result)
            }

            override fun onPaused() {
            }

            override fun onCanceled() {
            }

            override fun onFailed() {
            }
        })
        downloadManager.start(taskId)
    }


    override fun onDestroy() {
        downloadManager.cancelAll()
        downloadManager.unregisterListener()
        super.onDestroy()
    }


    /////////////////////////udp 中固件升级部分//////////////////////////////////////////

    private var mCanRegister: Boolean = false
    private var mIPAddress: String? = null

    override fun onResume() {
        super.onResume()
        if (mCanRegister) registerReceiver()
    }

    private fun registerReceiver() {
        val filter = IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            filter.addAction(LocationManager.PROVIDERS_CHANGED_ACTION)
        }
        mContext.registerReceiver(mReceiver, filter)
    }


    override fun onPause() {
        super.onPause()
        if (mCanRegister) mContext.unregisterReceiver(mReceiver)
    }

    @NeedsPermission(Manifest.permission.ACCESS_FINE_LOCATION)
    fun requestPermission() {
        onWifiChanged()
    }

    @OnPermissionDenied(Manifest.permission.ACCESS_FINE_LOCATION)
    fun permissionDenied() {
        android.app.AlertDialog.Builder(mContext)
            .setTitle("提示")
            .setMessage("在 Android M及以上版本，如果您禁止授权位置权限，APP将无法获取 Wi-Fi 信息")
            .setCancelable(false)
            .setPositiveButton(android.R.string.ok, null)
            .show()
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        onRequestPermissionsResult(requestCode, grantResults)
    }

    private fun onWifiChanged() {
        val locationManager = mContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager
        if (!LocationManagerCompat.isLocationEnabled(locationManager)) {
            mContext.showToast("请打开 GPS 以获取 Wi-Fi 信息")
            return
        }
        val wifiManager = mContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
        val wifiInfo = wifiManager.connectionInfo
        if (wifiInfo.networkId == -1 || wifiInfo.ssid == "<unknown ssid>") {
            mContext.showToast("请先连接 Wi-Fi")

            return
        }
        if (wifiInfo.frequency in 4901..5899) {
            mContext.showToast("当前连接的是 5G Wi-Fi, 设备仅支持 2.4G Wi-Fi")
            return
        }
        mIPAddress = wifiInfo.ipAddress.toIP()
    }

    private fun downloadMiddle(fileUrl: String, result: CommitResult) {
        val taskId = downloadManager.addTask(fileUrl)
        downloadManager.registerListener(taskId, object : OnDownloadListener {
            override fun onPending() {
                mConsoleAdapter.add("固件文件下载中...")
                progressBar.visibility = View.VISIBLE

            }

            override fun onProgress(progress: Long, total: Long) {
                progressBar.setProgress((progress * 100 / total).toInt())
            }

            override fun onCompleted(file: File) {
                progressBar.visibility = View.INVISIBLE
                startMiddleTask(result)
            }

            override fun onPaused() {
            }

            override fun onCanceled() {
            }

            override fun onFailed() {
            }
        })
        downloadManager.start(taskId)
    }

    private fun startMiddleTask(result: CommitResult) {
        val middleUrl = result.add3 ?: ""
        val middleCrc = result.add3_crc ?: ""
        val middleFile = File(mContext.downloadPath(), middleUrl.getFileName())

        when {
            // 判断是否可以升级
            result.ver == "0" -> {
                AlertDialog.Builder(mContext).apply {
                    setTitle("提示")
                    setMessage("固件升级已关闭,请选择菜单升级!")
                    setCancelable(false)
                    setPositiveButton("确定") { _, _ ->
                        startActivity(mContext.packageManager.getLaunchIntentForPackage(mContext.packageName)?.apply {
                            addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
                        })
                    }
                }.show()
            }
            // 版本低于服务器端版本,下载新固件
            result.ver != mContext.getSp().getString("ver", "") -> {
                mContext.setSp("ver", result.ver)
                middleFile.delete()
                downloadMiddle(middleUrl, result)

            }
            // 判断固件是否有缺失
            !middleFile.exists() -> downloadMiddle(middleUrl, result)
            // 判断是否有下载任务
            downloadManager.hasTask() -> mConsoleAdapter.add("固件下载中")
            // 文件 crc 校验
            !middleFile.matchCrc(middleCrc) -> {
                mConsoleAdapter.add("中固件校验失败,文件重新下载中")
                middleFile.delete()
                downloadMiddle(middleUrl, result)
            }
            // 开始升级
            else -> {
                ProgressDialog(mContext).apply {
                    setMessage("升级过程中禁止退出App，否则设备会变砖! ")
                    setCancelable(false)
                    setCanceledOnTouchOutside(false)
                    max = 100
                    setProgressStyle(ProgressDialog.STYLE_HORIZONTAL)
                    isIndeterminate = false
                    UDPMiddleTask(mIPAddress!!, middleFile).apply {
                        setOnProcessListener {
                            progress = it
                        }
                        setOnResultListener {
                            dismiss()
                            activity?.runOnUiThread { mContext.showToast(it) }
                        }
                        start()
                    }
                    show()
                }
            }
        }
    }

    private val mReceiver: BroadcastReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent) {
            if (intent.action == WifiManager.NETWORK_STATE_CHANGED_ACTION || intent.action == LocationManager.PROVIDERS_CHANGED_ACTION) {
                onWifiChanged()
            }
        }
    }
}